package org.intellij.doctree;

import org.intellij.doctree.node.*;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public class XMLHelper {

    public static void readDocuments(Element element, DocTreeModel treeModel) {
        if (treeModel == null) return;
        DocTreeNode root = (DocTreeNode) treeModel.getRoot();
        treeModel.clear();
        List docElements = element.getChildren("Documents");
        if (docElements != null && docElements.size() > 0) {
            Element docElement = (Element) docElements.get(0);
            readDocuments(docElement, treeModel, root);
        }
    }

    public static void writeDocuments(Element element, DocTreeModel treeModel) {
        if (treeModel == null) return;
        DocTreeNode root = (DocTreeNode) treeModel.getRoot();
        Element docElement = new Element("Documents");
        element.setContent(docElement);
        writeDocuments(docElement, root);
    }

    /**
     * Load from default doc, e.g. if first time plugin has been installed
     *
     * @param treeModel tree model
     */
    public static void readDefaultDocuments(DocTreeModel treeModel) {
        try {
            InputStream stream = XMLHelper.class.getResourceAsStream("/org/intellij/doctree/resources/default.xml");
            SAXBuilder builder = new SAXBuilder();
            org.jdom.Document doc = builder.build(stream);
            Element docRoot = doc.getRootElement();
            DocTreeNode root = (DocTreeNode) treeModel.getRoot();
            readDocuments(docRoot, treeModel, root);
        } catch (Exception e) {
            //ignore it
        }
    }

    public static List<String> readExpandedNodes(Element element, String treeName) {
        List treeElements = element.getChildren(treeName);
        if (treeElements == null || treeElements.size() == 0) return null;
        Element treeElement = (Element) treeElements.get(0);
        String rowsStr = treeElement.getText();
        String[] rows = rowsStr.split(":");
        if (rows == null) return null;
        List<String> rowsList = new ArrayList<String>();
        for (String row : rows) {
            if (row != null && row.length() > 0)
                rowsList.add(row);
        }
        return rowsList;
    }

    public static void writeExpandedNodes(Element element, String treeName, List<String> rows) {
        Element treeElement = new Element(treeName);
        element.addContent(treeElement);
        if (rows == null || rows.size() == 0) return;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < rows.size(); i++) {
            String row = rows.get(i);
            if (row != null) {
                if (i > 0) sb.append(":");
                sb.append(row);
            }
        }
        treeElement.setText(sb.toString());
    }

    private static void readDocuments(Element element, DocTreeModel model, DocTreeNode node) {
        DocTreeNode childNode = null;
        if (element.getName().equals("doc")) {
            Attribute nameAtt = element.getAttribute("name");
            Attribute urlAtt = element.getAttribute("url");
            Attribute descAtt = element.getAttribute("description");
            if (descAtt != null) {
                childNode = new DocumentNode(urlAtt.getValue(), nameAtt.getValue(), descAtt.getValue());
            } else {
                childNode = new DocumentNode(urlAtt.getValue(), nameAtt.getValue());
            }
        } else if (element.getName().equals("dir")) {
            Attribute nameAtt = element.getAttribute("name");
            Attribute descAtt = element.getAttribute("description");
            Attribute rootAtt = element.getAttribute("root");
            if (rootAtt == null) {
                if (descAtt != null) {
                    childNode = new FolderNode(nameAtt.getValue(), descAtt.getValue());
                } else {
                    childNode = new FolderNode(nameAtt.getValue());
                }
            }
        }
        if (childNode != null) {
            int index = node.getChildCount();
            model.insertNodeInto(childNode, node, index);
            node = childNode;
        }


        List childElements = element.getChildren();
        for (Object childElement : childElements) {
            Element childEl = (Element) childElement;
            readDocuments(childEl, model, node);
        }

    }

    private static void writeDocuments(Element element, DocTreeNode node) {
        Element childElement = null;
        if (node instanceof DocumentNode) {
            childElement = new Element("doc");
            Document doc = ((DocumentNode) node).getDocument();
            childElement.setAttribute("name", doc.getName());
            childElement.setAttribute("url", doc.getURL());
            if (doc.getDescription() != null && doc.getDescription().length() > 0)
                childElement.setAttribute("description", doc.getDescription());
        } else if (node instanceof FolderNode) {
            childElement = new Element("dir");
            Folder folder = ((FolderNode) node).getFolder();
            childElement.setAttribute("name", folder.getName());
            if (folder.getDescription() != null && folder.getDescription().length() > 0)
                childElement.setAttribute("description", folder.getDescription());
            if (node.isRoot()) childElement.setAttribute("root", "true");
        }
        element.addContent(childElement);

        for (int i = 0; i < node.getChildCount(); i++) {
            DocTreeNode childNode = (DocTreeNode) node.getChildAt(i);
            writeDocuments(childElement, childNode);
        }

    }


}
